#include "../list.h"


stListNode* list_create_node(void* data)
{
	stListNode* node = (stListNode*)malloc(sizeof(stListNode));

	if (node == NULL) return NULL;

	node->data = data; node->next = NULL;

	return node;
}

stListHandle* list_create()
{
	stListNode* node = NULL;
	stListHandle* handle = (stListHandle*)malloc(sizeof(stListHandle));
	
	if (handle == NULL) return NULL;

	if (node = list_create_node(NULL))
	{
		handle->head = handle->tail = node;
		handle->sz = 0;

		return handle;
	}

	free(handle);

	return NULL;
}

void list_clear(stListHandle* handle)
{
	stListNode* temp = NULL;
	stListNode* node = NULL;

	node = handle->head->next;

	while (temp = node)
	{
		node = node->next; free(temp);
	}

	handle->tail = handle->head;
	handle->sz = 0;
}

void list_destroy(stListHandle* handle)
{
	list_clear(handle);

	free(handle->head);
	free(handle);
}

void* list_push_back(stListHandle* handle, void* data)
{
	stListNode* node = list_create_node(data);
	
	if (node == NULL) return NULL;

	handle->tail->next = node;
	handle->tail = node;
	handle->sz++;

	return data;
}

void* list_push_front(stListHandle* handle, void* data)
{
	stListNode* node = list_create_node(data);

	if (node == NULL) return NULL;

	if (handle->sz++ == 0)
	{
		handle->tail = node;
	}
	else
	{
		node->next = handle->head->next;
	}

	handle->head->next = node;

	return data;
}

void* list_pop_front(stListHandle* handle)
{
	void* data = NULL;
	stListNode* node = NULL;

	if (handle->sz == 0) return NULL;

	node = handle->head->next;

	if (handle->sz-- == 1)
	{
		handle->tail = handle->head;
	}
	else
	{
		handle->head->next = node->next;
	}

	data = node->data; free(node);
	
	return data;
}

void* list_remove(stListHandle* handle, void* data)
{
	stListNode* pre = NULL;
	stListNode* node = NULL;

	if (handle->sz == 0) return NULL;

	pre = handle->head;

	while (node = pre->next)
	{
		if (node->data == data)
		{
			if (handle->tail == node)
			{
				handle->tail = pre;
			}

			pre->next = node->next;
			free(node);

			if (handle->sz-- == 1)
			{
				handle->tail = handle->head;
			}

			return data;
		}

		pre = node;
	}

	return NULL;
}

void* list_query(stListHandle* handle, ListQueryFunc func, void* data)
{
	int res = 0;
	stListNode* pre = NULL;
	stListNode* node = NULL;

	if (handle->sz == 0) return NULL;

	pre = handle->head;

	while (node = pre->next)
	{
		res = func(node, data);

		if (res > 0) return node->data;

		if (res < 0)
		{
			if (handle->tail == node)
			{
				handle->tail = pre;
			}

			pre->next = node->next;
			data = node->data;
			free(node);

			if (handle->sz-- == 1)
			{
				handle->tail = handle->head;
			}

			return data;
		}

		pre = node;
	}
	
	return NULL;
}